﻿using System.Linq;

namespace Nomad.WebSync.Pocket.Sync {
    class Appointments : SynchronizationControl {
        public Appointments() : base() { }

        public override void Start() {
            var remoteList = this.Service.GetAppointments();
            var localList = this.Session.GetDefaultFolder(PocketOutlook.OlDefaultFolders.olFolderCalendar);
            var count = remoteList.Count() + localList.Items.Count;
            var index = 1;

            foreach (var remote in remoteList) {
                this.DoProgressChanged(index++, count);

                if (remote.State == (byte)States.InsertOnMobile) {
                    this.insertLocal(remote);
                    continue;
                }

                if (remote.State == (byte)States.UpdateOnMobile) {
                    this.updateLocal(remote);
                    continue;
                }

                if (remote.State == (byte)States.RemoveFromMobile) {
                    this.removeLocal(remote);
                    continue;
                }

                var local = this.getLocal(remote.oid);
                if (local == null) {
                    this.removeRemote(remote);
                    continue;
                }

                if (local.IsChanged(remote)) {
                    this.updateRemote(local, remote);
                    continue;
                }
            }

            foreach (var item in localList.Items) {
                this.DoProgressChanged(index++, count);

                var local = (PocketOutlook.IAppointment)item;
                var remote = remoteList.SingleOrDefault(query => query.oid == local.oid);
                if (remote == null)
                    this.insertRemote(local);
            }
        }

        private PocketOutlook.IAppointment getLocal(int oid) {
            try {
                return (PocketOutlook.IAppointment)this.Session.GetItemFromOid(oid);
            } catch {
                return null;
            }
        }
        private PocketOutlook.IAppointment createNew() {
            return (PocketOutlook.IAppointment)this.Session.CreateItem((int)PocketOutlook.OlItemType.olAppointmentItem);
        }

        private void insertLocal(WebSyncService.Appointment remote) {
            var local = this.createNew();
            local.FromService(remote);
            local.Save();

            remote.oid = local.oid;
            this.Service.UpdateAppointment(remote);
        }
        private void updateLocal(WebSyncService.Appointment remote) {
            var local = this.getLocal(remote.oid);
            if (local == null) {
                this.insertLocal(remote);
            } else {
                local.FromService(remote);
                local.Save();
                this.Service.UpdateAppointment(remote);
            }
        }
        private void removeLocal(WebSyncService.Appointment remote) {
            var local = this.getLocal(remote.oid);
            if (local != null) local.Delete();
            this.Service.RemoveAppointment(remote);
        }

        private void insertRemote(PocketOutlook.IAppointment local) {
            this.updateRemote(local, new WebSyncService.Appointment());
        }
        private void updateRemote(PocketOutlook.IAppointment local, WebSyncService.Appointment remote) {
            remote.FromMobile(local);
            this.Service.UpdateAppointment(remote);
        }
        private void removeRemote(WebSyncService.Appointment remote) {
            this.Service.RemoveAppointment(remote);
        }
    }

    static class AppointmentsExtensions {
        public static bool IsChanged(this PocketOutlook.IAppointment mobile, WebSyncService.Appointment service) {
            if (service.AllDayEvent == mobile.AllDayEvent) return true;
            if (service.Body == mobile.Body) return true;
            if (service.BusyStatus == (byte)mobile.BusyStatus) return true;
            if (service.Categories == mobile.Categories) return true;
            if (service.Duration == mobile.Duration) return true;
            if (service.End == mobile.End) return true;
            if (service.Location == mobile.Location) return true;
            if (service.oid == mobile.oid) return true;
            if (service.ReminderMinutesBeforeStart == mobile.ReminderMinutesBeforeStart) return true;
            if (service.ReminderOptions == (byte)mobile.ReminderOptions) return true;
            if (service.ReminderSet == mobile.ReminderSet) return true;
            if (service.ReminderSoundFile == mobile.ReminderSoundFile) return true;
            if (service.Sensitivity == (byte)mobile.Sensitivity) return true;
            if (service.Start == mobile.Start) return true;
            if (service.Subject == mobile.Subject) return true;

            return false;
        }

        public static void FromService(this PocketOutlook.IAppointment mobile, WebSyncService.Appointment service) {
            mobile.AllDayEvent = service.AllDayEvent;
            mobile.Body = service.Body;
            mobile.BusyStatus = (PocketOutlook.OlBusyStatus)service.BusyStatus;
            mobile.Categories = service.Categories;
            mobile.Duration = service.Duration;
            mobile.End = service.End;
            mobile.Location = service.Location;
            mobile.ReminderMinutesBeforeStart = service.ReminderMinutesBeforeStart;
            mobile.ReminderOptions = (PocketOutlook.OlReminderOptions)service.ReminderOptions;
            mobile.ReminderSet = service.ReminderSet;
            mobile.ReminderSoundFile = service.ReminderSoundFile;
            mobile.Sensitivity = (PocketOutlook.OlSensitivity)service.Sensitivity;
            mobile.Start = service.Start;
            mobile.Subject = service.Subject;
        }

        public static void FromMobile(this WebSyncService.Appointment service, PocketOutlook.IAppointment mobile) {
            service.AllDayEvent = mobile.AllDayEvent;
            service.Body = mobile.Body;
            service.BusyStatus = (byte)mobile.BusyStatus;
            service.Categories = mobile.Categories;
            service.Duration = mobile.Duration;
            service.End = mobile.End;
            service.Location = mobile.Location;
            service.oid = mobile.oid;
            service.ReminderMinutesBeforeStart = mobile.ReminderMinutesBeforeStart;
            service.ReminderOptions = (byte)mobile.ReminderOptions;
            service.ReminderSet = mobile.ReminderSet;
            service.ReminderSoundFile = mobile.ReminderSoundFile;
            service.Sensitivity = (byte)mobile.Sensitivity;
            service.Start = mobile.Start;
            service.Subject = mobile.Subject;
        }
    }
}
